'Copyright (C) 2009 Christiaan Cable
'
'This program is free software; you can redistribute it and/or
'modify it under the terms of the GNU General Public License
'as published by the Free Software Foundation; either version 3
'of the License, or (at your option) any later version.
'
'This program is distributed in the hope that it will be useful,
'but WITHOUT ANY WARRANTY; without even the implied warranty of
'MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
'GNU General Public License for more details (LICENCE.TXT).

Imports System.Drawing
Imports ua
Imports System.IO

Module Module1
    Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uiAction As Integer, ByVal uiParam As Integer, ByVal pvParam As String, ByVal fWinIni As Integer) As Integer
    Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Integer, ByRef lpRect As System.Drawing.Rectangle) As Integer
    Public Declare Auto Function GetForegroundWindow Lib "user32" () As Int32

    Private AppDataPath As String = GetAppDataPath()

    Private WebForm As Form
    Private NewConfigurationData As New ConfigurationData

    'configuration data
    Private WallpaperFormList As New ArrayList

    'wallpaper bitmap
    Private Wallpaper As String
    Private WallpaperStyle As Integer
    '0=Center
    '1=Tile
    '2=Stretch
    Private WallpaperBitmap As Bitmap
    Private WallpaperBitmapGraphics As Graphics

    Sub Main()
        Try
            'already running, exit
            Dim myProcesses As Process() = Process.GetProcessesByName("UAWallpaper")
            If myProcesses.Length > 1 Then End
            myProcesses = Nothing

            If UnixDetected() = False Then
                'fullscreen? exit
                If IsFullScreenMode() Then End
            End If

            'check that the necessary files exist
            If Dir(AppDataPath & "usageagent.cfg") = "" Then
                MessageBox.Show("Cannot find usageagent.cfg. Usage Agent Configuration must be run prior to using this application.", "Usage Agent Wallpaper", MessageBoxButtons.OK, MessageBoxIcon.Error)
                End
            End If
            '############################################################

            Dim SourceWallpaper As Bitmap

            'load config
            If LoadConfiguration(NewConfigurationData) = True Then
                'if isp has not been validated, abort
                If NewConfigurationData.ISPValidated = False Then
                    MessageBox.Show("The connection to your ISP has not been validated. You must validate prior to running Usage Agent. Please re-run UA Configuration.", "Usage Agent Update", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                    End
                End If

                'get wallpaper
                If UnixDetected() = False Then
                    Dim RegKey As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\Microsoft\Internet Explorer\Desktop\General", False)
                    Wallpaper = Format(RegKey.GetValue("Wallpaper"))

                    If Wallpaper <> "" Then
                        If Wallpaper <> AppDataPath & "uawallpaper.bmp" Then
                            'copy existing wallpaper to local dir
                            If LCase(Wallpaper).EndsWith("bmp") = False Then
                                'convert to bmp
                                Dim TempBitmap As New Bitmap(Wallpaper)
                                TempBitmap.Save(AppDataPath & "source.bmp", Imaging.ImageFormat.Bmp)
                                TempBitmap.Dispose()
                            Else
                                FileCopy(Wallpaper, AppDataPath & "source.bmp")
                            End If
                        End If
                        Wallpaper = AppDataPath & "source.bmp"
                    End If

                    If CInt(RegKey.GetValue("TileWallpaper")) = 1 Then
                        WallpaperStyle = 1
                    Else
                        WallpaperStyle = CInt(RegKey.GetValue("WallpaperStyle"))
                    End If
                    RegKey.Close()
                Else
                    Wallpaper = Dir(AppDataPath & "source.*")
                    If Wallpaper <> "" Then
                        Wallpaper = AppDataPath & Wallpaper
                        WallpaperStyle = 2
                    Else
                        MessageBox.Show("The wallpaper source image cannot be found. Place file 'source.png' or 'source.jpg' in the dir " & AppDataPath, "Usage Agent Update", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                        End
                    End If
                End If

                'create bitmap the same size as the biggest display
                Dim MaxWidth As Integer = 0
                Dim MaxHeight As Integer = 0
                For Each NewScreen As Screen In System.Windows.Forms.Screen.AllScreens
                    If NewScreen.Bounds.Width > MaxWidth Then MaxWidth = NewScreen.WorkingArea.Width
                    If NewScreen.Bounds.Height > MaxHeight Then MaxHeight = NewScreen.Bounds.Height
                Next

                WallpaperBitmap = New Bitmap(MaxWidth, MaxHeight)
                WallpaperBitmapGraphics = Graphics.FromImage(WallpaperBitmap)

                'set to the current desktop color
                WallpaperBitmapGraphics.Clear(System.Drawing.SystemColors.Desktop)

                Dim DestinationRectangle As Rectangle
                If Wallpaper <> "" Then
                    'load source Wallpaper 
                    SourceWallpaper = CType(Bitmap.FromFile(Wallpaper), Bitmap)

                    'Create rectangle for target image
                    If WallpaperStyle = 0 Then
                        'centered
                        DestinationRectangle = New Rectangle(CInt((WallpaperBitmap.Width - SourceWallpaper.Width) / 2), CInt((WallpaperBitmap.Height - SourceWallpaper.Height) / 2), SourceWallpaper.Width, SourceWallpaper.Height)

                        'insert source Wallpaper into bitmap 
                        WallpaperBitmapGraphics.DrawImage(SourceWallpaper, DestinationRectangle, 0, 0, SourceWallpaper.Width, SourceWallpaper.Height, GraphicsUnit.Pixel)
                    ElseIf WallpaperStyle = 1 Then
                        'tiled
                        For x As Integer = 1 To CInt(Math.Ceiling(WallpaperBitmap.Width / SourceWallpaper.Width))
                            For y As Integer = 1 To CInt(Math.Ceiling(WallpaperBitmap.Height / SourceWallpaper.Height))
                                DestinationRectangle = New Rectangle(SourceWallpaper.Width * (x - 1), SourceWallpaper.Height * (y - 1), SourceWallpaper.Width, SourceWallpaper.Height)

                                'insert source Wallpaper into bitmap 
                                WallpaperBitmapGraphics.DrawImage(SourceWallpaper, DestinationRectangle, 0, 0, SourceWallpaper.Width, SourceWallpaper.Height, GraphicsUnit.Pixel)
                            Next
                        Next
                    ElseIf WallpaperStyle = 2 Then
                        'stretched
                        DestinationRectangle = New Rectangle(0, 0, WallpaperBitmap.Width, WallpaperBitmap.Height)

                        'set InterpolationMode
                        WallpaperBitmapGraphics.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic

                        'insert source Wallpaper into bitmap 
                        WallpaperBitmapGraphics.DrawImage(SourceWallpaper, DestinationRectangle, 0, 0, SourceWallpaper.Width, SourceWallpaper.Height, GraphicsUnit.Pixel)
                    End If

                    SourceWallpaper.Dispose()
                End If

                'generate each form
                For Each NewWallpaperFormData As WallpaperFormData In NewConfigurationData.WallpaperFormList
                    If NewWallpaperFormData.FormType = 0 Then
                        If UnixDetected() = False Then
                            NewShell(AppDataPath, Application.StartupPath & Path.DirectorySeparatorChar & "uaimage.exe", "", True)
                        Else
                            NewShell(Application.StartupPath, "mono", "uaimage.exe", False)
                        End If

                        'load source Wallpaper 
                        Dim UABitmap As Bitmap = CType(Bitmap.FromFile(AppDataPath & "uaimage.png"), Bitmap)

                        'set opacity
                        Dim cm As New System.Drawing.Imaging.ColorMatrix
                        cm.Matrix33 = CSng(NewConfigurationData.Opacity)

                        ' Create an ImageAttributes object and set its color matrix.
                        Dim ia As New System.Drawing.Imaging.ImageAttributes
                        ia.SetColorMatrix(cm)

                        'insert ISPGraph in Wallpaper
                        WallpaperBitmapGraphics.DrawImage(UABitmap, New Rectangle(CInt(NewWallpaperFormData.X), CInt(NewWallpaperFormData.Y), UABitmap.Width, UABitmap.Height), 0, 0, UABitmap.Width, UABitmap.Height, GraphicsUnit.Pixel, ia)
                        UABitmap.Dispose()

                    ElseIf NewWallpaperFormData.FormType = 1 Then
                        'webimage
                        CreateWebForm(NewWallpaperFormData)
                    End If
                Next

                'save wallpaper bitmap
                If UnixDetected() = False Then
                    Wallpaper = "uawallpaper.bmp"
                    WallpaperBitmap.Save(AppDataPath & Wallpaper, System.Drawing.Imaging.ImageFormat.Bmp)
                Else
                    Wallpaper = "uawallpaper.png"
                    WallpaperBitmap.Save(AppDataPath & Wallpaper, System.Drawing.Imaging.ImageFormat.Png)
                End If

                'clean up
                WallpaperBitmap.Dispose()
                WallpaperBitmapGraphics.Dispose()

                'set wallpaper
                SetWallpaper(AppDataPath & Wallpaper, 1)
            Else
                'set to default if it exists
                If UnixDetected() = False Then
                    Wallpaper = "uawallpaper.bmp"
                Else
                    Wallpaper = "uawallpaper.png"
                End If
                If Dir(AppDataPath & Wallpaper) <> "" Then
                    SetWallpaper(AppDataPath & Wallpaper, 1)
                End If
            End If

        Catch ex As Exception
            MessageBox.Show(ex.Message, "Usage Agent", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            'set to default if it exists
            If Dir(AppDataPath & "wallpaper.bmp") <> "" Then
                SetWallpaper(AppDataPath & "wallpaper.bmp", 1)
            End If
        Finally
            'clean up
            If WebForm IsNot Nothing Then WebForm.Dispose()
        End Try
    End Sub

    Sub SetWallpaper(ByVal FileName As String, Optional ByVal WallpaperStyle As Integer = 0)
        Try
            If UnixDetected() = False Then
                '0 = Stretched
                '1 = Centered
                '2 = Tiled

                'set Wallpaper Style
                Dim key As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Control Panel\Desktop\", True)

                If WallpaperStyle = 0 Then
                    'stretched
                    key.SetValue("WallpaperStyle", "2")
                    key.SetValue("TileWallpaper", "0")
                ElseIf WallpaperStyle = 1 Then
                    'Centered 
                    key.SetValue("WallpaperStyle", "1")
                    key.SetValue("TileWallpaper", "0")
                ElseIf WallpaperStyle = 2 Then
                    'Tiled 
                    key.SetValue("WallpaperStyle", "1")
                    key.SetValue("TileWallpaper", "1")
                End If

                'set Wallpaper image
                Const SPI_SETDESKWallpaper As Integer = &H14
                Const SPIF_UPDATEINIFILE As Integer = &H1
                Const SPIF_SENDWININICHANGE As Integer = &H2
                Const SPIF_SENDCHANGE As Integer = SPIF_SENDWININICHANGE
                SystemParametersInfo(SPI_SETDESKWallpaper, 0, FileName, SPIF_UPDATEINIFILE Or SPIF_SENDCHANGE)
            Else
                If NewConfigurationData.WallpaperUnixCommand <> "" Then
                    NewShell(AppDataPath, NewConfigurationData.WallpaperUnixCommand, NewConfigurationData.WallpaperUnixCommandArgs, False)
                End If
            End If

        Catch ex As Exception
            MessageBox.Show(ex.Message, "Usage Agent", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        End Try

    End Sub

    Sub CreateWebForm(ByVal FormData As WallpaperFormData)
        Dim XOffset As Integer
        Dim YOffset As Integer = 0
        Dim NewString As String

        If FormData.ShowLabel = True Then YOffset = 15

        Dim UABitmap As New Bitmap(CInt(FormData.Width), CInt(FormData.Height) + YOffset)
        Dim g As Graphics = Graphics.FromImage(UABitmap)

        'clear background
        g.Clear(Color.Transparent)

        'set quality
        If FormData.ShowBackground = True Then
            g.TextRenderingHint = Text.TextRenderingHint.ClearTypeGridFit
        Else
            g.TextRenderingHint = Text.TextRenderingHint.SystemDefault
        End If

        'set fonts
        Dim myRegularFont As New Font("Verdana", CSng(7 * (96 / GetDPI())), FontStyle.Regular)

        'set colour
        Dim myBrush As New SolidBrush(Color.FromArgb(CInt(FormData.ForeColour)))
        YOffset = 0

        '###########################################################

        If FormData.ShowLabel = True Then
            If FormData.ShowBackground = True Then DrawRoundedRectangle(g, 0, 0, CInt(FormData.Width) - 1, 13, Color.FromArgb(CInt(FormData.BackColour)), True, True)

            NewString = FormData.Label & " @ " & Format(Now, "h:mm tt")

            XOffset = CInt((-g.MeasureString(NewString, myRegularFont, 1000, StringFormat.GenericTypographic).Width / 2) + 5)
            g.ResetTransform()
            g.TranslateTransform(CInt(Val(FormData.Width) / 2), 4, Drawing.Drawing2D.MatrixOrder.Append)

            DrawOutlinedText(FormData.ShowBackground, Color.FromArgb(CInt(FormData.ForeColour)), g, NewString, myRegularFont, XOffset, YOffset - 4)

            YOffset = 13 + 2
        End If

        'draw background
        If FormData.ShowBackground = True Then DrawRoundedRectangle(g, 0, YOffset, CInt(FormData.Width) - 1, CInt(FormData.Height) - 1, Color.FromArgb(CInt(FormData.BackColour)), True, True)

        Dim NewInet As New System.Net.WebClient
        Dim DestinationRectangle As Rectangle

        Try
            Dim SourceBitmap As Bitmap

            'get web image
            SourceBitmap = New Bitmap(NewInet.OpenRead(FormData.URL))
            NewInet.Dispose()

            'set InterpolationMode
            g.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic

            Dim NewWidth, NewHeight As Double
            Dim ImageOffset As Integer = 4
            Dim SourceRectangle As Rectangle
            Dim NewX, NewY As Integer

            If FormData.StretchImage = False Then
                'Create source rectangle for source image
                If FormData.Zoom = True Then
                    'user defined
                    SourceRectangle = New Rectangle(CInt(FormData.ZoomX), CInt(FormData.ZoomY), CInt((CDbl(FormData.Width) - ImageOffset)), CInt(CDbl(FormData.Height) - ImageOffset))
                Else
                    'centered
                    SourceRectangle = New Rectangle(CInt((SourceBitmap.Width / 2) - ((CDbl(FormData.Width) - ImageOffset) / 2)), CInt((SourceBitmap.Height / 2) - ((CDbl(FormData.Height) - ImageOffset) / 2)), CInt(CDbl(FormData.Width) - ImageOffset), CInt(CDbl(FormData.Height) - ImageOffset))
                End If
            Else
                'Create rectangle for target image (stretched)
                If FormData.MaintainAspectRatio = False Then
                    If FormData.Zoom = True Then
                        'user defined
                        SourceRectangle = New Rectangle(CInt(FormData.ZoomX), CInt(FormData.ZoomY), CInt(FormData.ZoomWidth), CInt(FormData.ZoomHeight))
                    Else
                        'centered
                        SourceRectangle = New Rectangle(0, 0, SourceBitmap.Width, SourceBitmap.Height)
                    End If
                Else
                    Dim AspectRatio As Double
                    Dim SourceWidth As Integer
                    Dim SourceHeight As Integer

                    If FormData.Zoom = True Then
                        'user defined
                        SourceWidth = CInt(FormData.ZoomWidth)
                        SourceHeight = CInt(FormData.ZoomHeight)
                    Else
                        'centered
                        SourceWidth = SourceBitmap.Width
                        SourceHeight = SourceBitmap.Height
                    End If

                    AspectRatio = (CDbl(FormData.Width) - ImageOffset) / (CDbl(FormData.Height) - ImageOffset)

                    If SourceWidth > SourceHeight Then
                        NewHeight = SourceHeight
                        NewWidth = (SourceHeight / AspectRatio)
                    Else
                        NewWidth = SourceWidth
                        NewHeight = (SourceWidth / AspectRatio)
                    End If

                    If FormData.Zoom = True Then
                        'user defined
                        SourceRectangle = New Rectangle(CInt(CDbl(FormData.ZoomX) + (-(NewWidth - SourceWidth) / 2)), CInt(CDbl(FormData.ZoomY) + (-(NewHeight - SourceHeight) / 2)), CInt(NewWidth), CInt(NewHeight))
                    Else
                        'centered
                        SourceRectangle = New Rectangle(-CInt((NewWidth - SourceWidth) / 2), -CInt((NewHeight - SourceHeight) / 2), CInt(NewWidth), CInt(NewHeight))
                    End If

                End If
            End If

            'Create destination rectangle for target image
            If (CDbl(FormData.Width) - ImageOffset) < SourceBitmap.Width Then
                NewX = CInt(0 + (ImageOffset / 2))
            Else
                NewX = CInt(0 + ((CDbl(FormData.Width) - ImageOffset - SourceBitmap.Width) / 2))
            End If
            If (CDbl(FormData.Height) - ImageOffset) < SourceBitmap.Height Then
                NewY = CInt(YOffset + (ImageOffset / 2))
            Else
                NewY = 0 + CInt(((CDbl(FormData.Height) - ImageOffset - SourceBitmap.Height) / 2))
            End If
            DestinationRectangle = New Rectangle(NewX, NewY, CInt(CDbl(FormData.Width) - ImageOffset), CInt(CDbl(FormData.Height) - ImageOffset))

            'insert source Wallpaper into bitmap 
            g.DrawImage(SourceBitmap, DestinationRectangle, SourceRectangle, GraphicsUnit.Pixel)

            SourceBitmap.Dispose()

        Catch ex As Exception
            Try
                'set quality
                g.TextRenderingHint = Text.TextRenderingHint.ClearTypeGridFit

                g.ResetTransform()
                Try
                    'draw error text
                    g.ResetTransform()
                    Dim NewStringFormat As New StringFormat
                    NewStringFormat.FormatFlags = StringFormatFlags.FitBlackBox
                    NewStringFormat.Alignment = StringAlignment.Center
                    Dim layoutSize As New SizeF(CSng(FormData.Width), CSng(FormData.Height))
                    Dim stringSize As New SizeF(g.MeasureString(ex.Message, myRegularFont, layoutSize, NewStringFormat))
                    'define bounding rectangle in which to draw
                    Dim StartY As Single = CSng(((CDbl(FormData.Height) - stringSize.Height) / 2))
                    Dim DrawRect As New RectangleF(0, StartY, CSng(FormData.Width), stringSize.Height)
                    g.DrawString(ex.Message, myRegularFont, myBrush, DrawRect, NewStringFormat)
                    NewStringFormat.Dispose()
                Catch ex1 As Exception
                End Try

            Catch ex1 As Exception
            End Try
            'if connection is still open, then close it
            If NewInet IsNot Nothing Then NewInet.Dispose()
        End Try

        '##########################################################

        'Create rectangle for target image.
        DestinationRectangle = New Rectangle(CInt(FormData.X), CInt(FormData.Y), UABitmap.Width, UABitmap.Height)

        'insert ISPGraph in Wallpaper
        'set opacity
        Dim cm As New System.Drawing.Imaging.ColorMatrix
        cm.Matrix33 = CSng(FormData.Opacity)

        ' Create an ImageAttributes object and set its color matrix.
        Dim ia As New System.Drawing.Imaging.ImageAttributes
        ia.SetColorMatrix(cm)

        WallpaperBitmapGraphics.DrawImage(UABitmap, DestinationRectangle, 0, 0, UABitmap.Width, UABitmap.Height, GraphicsUnit.Pixel, ia)

        '########################################################

        'clean up
        ia.Dispose()
        myRegularFont.Dispose()
        myBrush.Dispose()

        g.Dispose()
        UABitmap.Dispose()

    End Sub

    Private Function IsFullScreenMode() As Boolean
        Dim rcWindow As System.Drawing.Rectangle
        Dim hWnd As Integer = GetForegroundWindow()
        If hWnd > 0 Then
            GetWindowRect(hWnd, rcWindow)
            If (Screen.PrimaryScreen.Bounds.Width = (rcWindow.Right - rcWindow.Left)) AndAlso (Screen.PrimaryScreen.Bounds.Height = (rcWindow.Bottom - rcWindow.Top)) Then
                Return True
            End If
        End If
        Return False
    End Function
End Module
